package zhongche.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zhongche.bean.DataTypeInfo;
import com.zhongche.bean.Edges;
import com.zhongche.bean.Nodes;
import org.apache.commons.io.IOUtils;
import org.apache.flink.api.java.tuple.Tuple2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.soap.Node;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class RulesUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(RulesUtil.class);

    private static final String NODES = "nodes";

    private static final String EDGES = "edges";

    private static final String RESULT = "result";


    /**
     * 读取规则问价
     *
     * @param filePath
     * @return
     */
    public static String paresRuleByFile(String filePath) {
        StringBuilder sb = new StringBuilder();
        FileInputStream fis = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(RulesUtil.class.getClassLoader().getResource(filePath).getPath());
            br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        } catch (FileNotFoundException e) {
            LOGGER.info(filePath + "文件未找到");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;

    }

    public static List<Map<String, List<Nodes>>> parseRuleByString(String viewInfo) {
        JSONObject jsonObject = JSONObject.parseObject(viewInfo);
//        System.out.println(jsonObject.getJSONArray("nodes").get(0).toString());
        JSONArray jsonArrayNodes = jsonObject.getJSONArray(NODES);
        JSONArray jsonArrayEdges = jsonObject.getJSONArray(EDGES);
        Map<String, Nodes> nodesMap = new HashMap<>();
        List<Nodes> nodesList = new ArrayList<>();
        List<Edges> edgesList = new ArrayList<>();
        Map<String, List<String>> edgesMap = new HashMap<>();
        for (Object obj : jsonArrayNodes) {
            Nodes nodes = TransObjUtil.transJSONObjToNodes((JSONObject) obj);
            nodesList.add(nodes);
            nodesMap.put(nodes.getId(), nodes);
//            System.out.println(JSONObject.toJSONString(nodes));
        }
        for (Object obj : jsonArrayEdges) {
            JSONObject jsObj = (JSONObject) obj;
            Edges edges = JSONObject.parseObject(jsObj.toJSONString(), Edges.class);
            edgesList.add(edges);
            List<String> sourceList = edgesMap.get(edges.getTarget());
            if (sourceList == null) {
                sourceList = new ArrayList<>();
            }
            if (!sourceList.contains(edges.getSource())) {
                sourceList.add(edges.getSource());
            }
            edgesMap.put(edges.getTarget(), sourceList);
        }

        String resultId = getResourceNodeId(nodesList);

        return rankNodesByResultId(nodesMap, edgesMap, resultId);

    }

    /**
     * 解析 nodeList
     *
     * @param viewInfo
     * @return
     */
    public static List<Nodes> parseListNodesByString(String viewInfo) {
        JSONObject jsonObject = JSONObject.parseObject(viewInfo);
        JSONArray jsonArrayNodes = jsonObject.getJSONArray(NODES);
        List<Nodes> nodesList = new ArrayList<>();
        for (Object obj : jsonArrayNodes) {
            Nodes nodes = TransObjUtil.transJSONObjToNodes((JSONObject) obj);
            nodesList.add(nodes);
        }
        return nodesList;
    }


    /**
     * 获取 edges 映射
     *
     * @param viewInfo
     * @return
     */
    public static Map<String, List<String>> getEdgesMapByTargetKey(String viewInfo) {
        Map<String, List<String>> edgesMap = new HashMap<>();
        JSONObject jsonObject = JSONObject.parseObject(viewInfo);
        JSONArray jsonArrayEdges = jsonObject.getJSONArray(EDGES);
        for (Object obj : jsonArrayEdges) {
            JSONObject jsObj = (JSONObject) obj;
            Edges edges = JSONObject.parseObject(jsObj.toJSONString(), Edges.class);
            List<String> sourceList = edgesMap.get(edges.getTarget());
            if (sourceList == null) {
                sourceList = new ArrayList<>();
            }
            if (!sourceList.contains(edges.getSource())) {
                sourceList.add(edges.getSource());
            }
            edgesMap.put(edges.getTarget(), sourceList);
        }
        return edgesMap;
    }





    /**
     * 获取 result 节点id
     *
     * @param nodesList
     * @return
     */
    public static String getResourceNodeId(List<Nodes> nodesList) {
        for (Nodes node : nodesList) {
            if (node.getShape().equals(RESULT)) {
                return node.getId();
            }
        }
        return null;
    }

    /**
     * nodesList 转nodesMap
     *
     * @param nodesList
     * @return
     */
    public static Map<String, Nodes> nodesListToNodesMap(List<Nodes> nodesList) {
        Map<String, Nodes> nodesMap = new HashMap<>();
        for (Nodes nodes: nodesList) {
            nodesMap.put(nodes.getId(),nodes);
        }
        return nodesMap;
    }


    /**
     * 解析 流程文件
     *
     * @param nodesMap
     * @param edgesMap
     * @param resultId
     * @return
     */
    public static List<Map<String, List<Nodes>>> rankNodesByResultId(Map<String, Nodes> nodesMap, Map<String, List<String>> edgesMap, String resultId) {
        List<Map<String, List<Nodes>>> linkList = new ArrayList<>();
        Tuple2<Map<String, List<Nodes>>, List<String>> tuple2 = getNodesMap(Collections.singletonList(resultId), nodesMap, edgesMap);
        linkList.add(tuple2.f0);
        List<String> sourceIds = tuple2.f1;
        while (sourceIds.size() > 0) {
            Tuple2<Map<String, List<Nodes>>, List<String>> listTuple2 = getNodesMap(sourceIds, nodesMap, edgesMap);
            if (listTuple2.f0.size() > 0) {
                linkList.add(listTuple2.f0);
            }
            sourceIds = listTuple2.f1;
        }
        return linkList;
    }


    /**
     * 根据输出节点id 获取输入节点
     *
     * @param targetList
     * @param nodesMap
     * @param edgesMap
     * @return
     */
    public static Tuple2<Map<String, List<Nodes>>, List<String>> getNodesMap(List<String> targetList, Map<String, Nodes> nodesMap, Map<String, List<String>> edgesMap) {
        Map<String, List<Nodes>> nodesHashMap = new HashMap<>();
        List<String> strings = new ArrayList<>();
        for (String str : targetList) {
            List<String> sourceList = edgesMap.get(str);
            if (sourceList != null) {
                List<Nodes> list = new ArrayList<>();
                for (String s : sourceList) {
                    list.add(nodesMap.get(s));
                }
                nodesHashMap.put(str, list);
                strings.addAll(sourceList);
            }

        }
        return Tuple2.of(nodesHashMap, strings);
    }

    public static List<String> getSourceIdByTargetId(String targetId, List<Edges> edgesList) {
        List<String> list = new ArrayList<>();
        for (Edges edges : edgesList) {
            if (edges.getTarget().equals(targetId)) {
                list.add(edges.getSource());
            }
        }
        return list;
    }


    public static void main(String[] args) {
        String s = paresRuleByFile("rules/viewInfo.txt");
        List<Map<String, List<Nodes>>> maps = parseRuleByString(s);
        System.out.println(maps.get(0));
    }
}
